#!/bin/sh

e2e_use_extensions() {
  true
}

e2e_test_install() {
  DBOPS_NAME=repack

  PG_REPACK_VERSION="$(get_latest_version_of_extension pg_repack "${E2E_POSTGRES_VERSION%.*}")"

  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" 1 \
    --set-string cluster.postgres.extensions[0].version="$PG_REPACK_VERSION"

  wait_pods_running "$CLUSTER_NAMESPACE" 1
  wait_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"
}

e2e_test() {
  run_test "Checking that repack is working" check_repack_is_working

  run_test "Checking that repack no order is working" check_repack_no_order_is_working

  run_test "Checking that repack wait timeout is working" check_repack_wait_timeout_is_working

  run_test "Checking that repack no kill backend is working" check_repack_no_kill_backend_is_working

  run_test "Checking that repack no analyze is working" check_repack_no_analyze_is_working

  run_test "Checking that repack exclude extension is working" check_repack_exclude_extension_is_working

  run_test "Checking that repack is working for specific databases" check_repack_specific_databases_is_working

  run_test "Checking that repack timeout works correctly" check_repack_timed_out
}

check_repack_is_working() {
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
EOF

  wait_until eval '[ "$(kubectl get sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME" \
    --template "{{ .status.opRetries }}")" = "0" ]'
  kubectl get sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME" -o yaml > "$LOG_PATH/sgdbops.yaml"
  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
  kubectl create -f "$LOG_PATH/sgdbops.yaml"

  check_repack

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
}

check_repack_no_order_is_working() {
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
  repack:
    noOrder: true
EOF

  check_repack

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
}

check_repack_wait_timeout_is_working() {
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
  repack:
    waitTimeout: PT1S
EOF

  check_repack

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
}

check_repack_no_kill_backend_is_working() {
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
  repack:
    noKillBackend: true
EOF

  check_repack

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
}

check_repack_no_analyze_is_working() {
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
  repack:
    noAnalyze: true
EOF

  check_repack

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
}

check_repack_exclude_extension_is_working() {
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
  repack:
    excludeExtension: true
EOF

  check_repack

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
}

check_repack_specific_databases_is_working() {
  run_query -p 5432 -h "$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -c "$CLUSTER_NAME" \
    -q "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'template1' AND pid != pg_backend_pid()"
  run_query -p 5432 -h "$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -c "$CLUSTER_NAME" \
    -q "CREATE DATABASE test1"
  run_query -p 5432 -h "$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -c "$CLUSTER_NAME" \
    -q "CREATE DATABASE test2;"
  run_query -p 5432 -h "$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -c "$CLUSTER_NAME" \
     -d "test1" -q "CREATE EXTENSION pg_repack"
  run_query -p 5432 -h "$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -c "$CLUSTER_NAME" \
     -d "test2" -q "CREATE EXTENSION pg_repack"
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
  repack:
    databases:
    - name: test1
      noOrder: true
    - name: test2
      noKillBackend: true
EOF

  check_repack

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"
}

check_repack() {
  assert_dbops_running "$DBOPS_NAME" "$CLUSTER_NAMESPACE"

  assert_dbops_completion "$DBOPS_NAME" "$CLUSTER_NAMESPACE"

  if [ "$(kubectl get -n "$CLUSTER_NAMESPACE" job \
    -l "stackgres.io/dbops-name=$DBOPS_NAME,stackgres.io/db-ops=true" \
    -o name 2>/dev/null | wc -l)" = 1 ]
  then
    success "repack job was not removed after completion."
  else
    fail "repack job was removed after completion."
  fi
}

check_repack_timed_out() {
  run_query -p 5432 -h "$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -c "$CLUSTER_NAME" \
     -q "CREATE TABLE public.test(i int PRIMARY KEY)"
  run_query -p 5432 -h "$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -c "$CLUSTER_NAME" \
     -q "$(cat << 'EOF'
DO $$BEGIN
  LOCK TABLE public.test;
  PERFORM pg_sleep(600);
END$$;
EOF
      )" &
  trap_kill "$!"
  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NAMESPACE
spec:
  sgCluster: $CLUSTER_NAME
  op: repack
  timeout: PT1S
EOF

  if kubectl wait --timeout "${E2E_TIMEOUT}s" -n "$CLUSTER_NAMESPACE" sgdbops "$DBOPS_NAME" \
    --for condition=Completed \
    && kubectl wait --timeout "0s" -n "$CLUSTER_NAMESPACE" sgdbops "$DBOPS_NAME" \
    --for condition=Failed
  then
    success "repack failed."
  else
    fail "repack did not fail."
  fi

  if [ "$(kubectl get -n "$CLUSTER_NAMESPACE" job \
    -l "stackgres.io/dbops-name=$DBOPS_NAME,stackgres.io/db-ops=true" \
    -o name 2>/dev/null | wc -l)" = 1 ]
  then
    success "repack job was not removed after failure."
  else
    fail "repack job was removed after failure."
  fi

  kubectl delete sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME"

  if wait_until eval '[ "$(kubectl get -n "$CLUSTER_NAMESPACE" job \
    -l "stackgres.io/dbops-name=$DBOPS_NAME,stackgres.io/db-ops=true" \
    -o name 2>/dev/null | wc -l)" = 0 ]'
  then
    success "repack job was removed after sgdbops was removed."
  else
    fail "repack job was not removed after sgdbops was removed."
  fi
}
